package com.example.demo.redislock;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.params.SetParams;

import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.Random;


@Service
public class RedisTool {

    private String dataCacheHost="127.0.0.1";

    private int dataCachePort=6379;

    private int dataCacheDb=0;

    private int dataCacheExpire=100;

    private volatile JedisPool jedisPool = null;

    private static JedisPoolConfig jpc = new JedisPoolConfig();

    static {
        jpc.setMaxIdle(64);
        jpc.setMaxTotal(256);
        jpc.setMaxWaitMillis(30000);
    }

    public JedisPool getJedisPool() {
        if (jedisPool == null) {
            synchronized(RedisTool.class) {
                if (jedisPool == null) {
                    jedisPool = new JedisPool(jpc, dataCacheHost, dataCachePort, 10000, null, dataCacheDb);
                }
            }
        }
        return jedisPool;
    }

    public String getRowKey(String prefix, Object ... params) throws UnsupportedEncodingException {
        StringBuffer buffer = new StringBuffer();
        for(Object p : params) {
            buffer.append(p);
        }

        return prefix + ":" + DigestUtils.md5DigestAsHex(buffer.toString().getBytes("UTF-8"));
    }

    public String get(String key) {
        Jedis jedis = getJedisPool().getResource();
        String value = jedis.get(key);
        jedis.close();
        return value;
    }

    public void set(String key, String value) {
        Jedis jedis = getJedisPool().getResource();
        int expireTime = dataCacheExpire / 2 + new Random().nextInt(dataCacheExpire / 2);
        jedis.setex(key, expireTime, value);
        jedis.close();
    }

    public void set(String key, String value, int time){
        Jedis jedis = getJedisPool().getResource();
        jedis.setex(key, time, value);
        jedis.close();
    }

    public boolean lock(String key,String value, int timeout) {
        Jedis jedis = getJedisPool().getResource();
        return "OK".equals(jedis.set(key, value, SetParams.setParams().nx().ex(timeout)));
    }

    /**
     * 使用Lua脚本进行解锁操纵，解锁的时候验证value值
     *
     * @param key
     * @param value
     * @return
     */
    public boolean unlock(String key,String value) {
        Jedis jedis = getJedisPool().getResource();
        String luaScript = "if redis.call('get',KEYS[1]) == ARGV[1] then " +
                "return redis.call('del',KEYS[1]) else return 0 end";
        return jedis.eval(luaScript, Collections.singletonList(key), Collections.singletonList(value)).equals(1L);
    }
}
